<?php
/**
 * Protoweb's base controller with base functionality
 */
include_once 'pwcontroller.php';
include_once 'projects.php';


/**
 * The controller entity model
 *
 * Public controller methods are friendly urls thanks to {@link http://codeigniter.com
 * Codeigniter}.
 *
 * @author Gonzalez Federico, Viera Leonel
 * @package Protoweb
 * @subpackage controller
 */
class Entities extends PwController
{

    public function __construct()
    {
        parent::__construct();
    } 

    /**
     * This method grant users the posibility to create a new entity for a particular project
     *
     * @param integer $project_id Working project's id
     */
    public function create($project_id)
    {
        // Checking permissions user
        $data['user']    = Projects::security($project_id, 'member');
        $data['project'] = new Project($project_id);
        $data['entity']  = new Entity();

        if ($this->input->server('REQUEST_METHOD') === 'POST') {
            $data = $this->create_save($data['project']->id);
        }

        $this->smartyview->render('entity_create.html', $data);
    } // end of method create


    private function create_save($project_id) 
    {
        $data['user']                = Projects::security($project_id, 'member');
        $data['project']             = new Project($project_id);
        $data['entity']              = new Entity();
        $data['entity']->plural      = $this->input->post('plural');
        $data['entity']->singular    = $this->input->post('singular');
        $data['entity']->description = $this->input->post('description');

        if ($data['entity']->firstSave($data['project'])) {
            redirect(base_url().'projects/dashboard/' . $data['project']->id . '/');
        }
        else {
            $data['error'] = $data['entity']->error->string;
            return($data);
        }
    } // create_save


    /**
     * This method grant users the posibility to edit an entity of a particular project
     *
     * @param integer $entity_id The ID of the entity that is going to be modified
     */
    public function edit($entity_id,$active_tab='basic')
    {
        $data['entity'] = new Entity($entity_id);
        $data['user']   = Projects::security($data['entity']->project->id, 'member');
        $data['active_tab'] = $active_tab;

        if ($this->input->server('REQUEST_METHOD') === 'POST') {
            $data = $this->edit_save();
        }

        $data['project'] = new Project($data['entity']->project->id);

        $this->smartyview->render('entity_edit.html', $data);
    } // end of method edit


    /**
     * This method grant users the posibility to edit an entity of a particular project
     *
     * @param integer $entity_id The ID of the entity that is going to be modified
     */
    public function content($entity_id)
    {
        $data['entity'] = new Entity($entity_id);

        $this->smartyview->render('entity_content_dashboard.html', $data);
    } // end of method edit


    /**
     * Save changes made to an entity
     * 
     * This method updates Protoweb's DB, updates generated project's DB, and regenerate
     * all protoweb's generated files in generated project's directory
     *
     * @return array if error, else redirects
     */
    private function edit_save()
    {
        $data['entity'] = new Entity($this->input->post('id'));
        $data['user']   = Projects::security($data["entity"]->project->id, "member");

        // Modify entiy singular and plural and refactor generated DB and files
        if ($data['entity']->saveAndRefactor(
                $this->input->post('plural'),
                $this->input->post('singular'),
                $this->input->post('description')
            ) ){

            $attrIDs      = $this->input->post("attr_id");
            $attrNames    = $this->input->post("attr_name");
            $attrLabels   = $this->input->post("attr_label");
            $attrRules    = $this->input->post("attr_rules");
            $attrPurposes = $this->input->post("purposes");

            if ( ! is_array($attrIDs)) {
                $attrIDs = array();
            }

            // Delete attributes
            foreach ($data["entity"]->attribute as $attribute) {
                if ( ! in_array($attribute->id, $attrIDs)) {
                    $attribute->delete();
                }
            }

            // Save attributes (create and update)
            for ($i = 0; $i < count($attrIDs); $i++) {
                $attribute = new Attribute($attrIDs[$i]);
                
                if ($attribute->id == null) {
                    $attribute->firstSave(
                        $attrNames[$i],
                        $attrLabels[$i],
                        $attrRules[$i],
                        $data['entity']->id,
                        $attrPurposes[$i]
                    );
                }   
                else {
                    $attribute->saveAndRefactor(
                        $attrNames[$i],
                        $attrLabels[$i],
                        $attrRules[$i],
                        $attrPurposes[$i]
                    );
                }
            }

            // re initialize and generate pw model and controller
            $data['entity'] = new Entity($this->input->post('id'));
            $data['entity']->generateModelFiles(false);
            $data['entity']->generateControllerFiles(false);

            redirect(base_url().'projects/dashboard/' . $data["entity"]->project->id . '/');
        }
        else {
            $data['error'] = $data['entity']->error->string;
            return($data);
        }
    } // edit_save


    public function generate_crud($entityID)
    {
        // Checking permissions user
        $data['entity']  = new Entity($entityID);
        $data['project'] = $data['entity']->project;
        $data['user']    = Projects::security($data['project']->id, "member");

        if ($this->input->server('REQUEST_METHOD') === 'POST') {
            $data = $this->generate_crud_save($data['entity']->id);
        }

        $this->smartyview->render('entity_generate_crud.html', $data);
    } // end of method create

    private function generate_crud_save($entityID)
    {
        $data['entity']  = new Entity($entityID);
        $data['project'] = $data['entity']->project;
        $data['user']    = Projects::security($data['project']->id, "member");
        $crud            = "";

        // create controller
        if ($this->input->post('create_check')) {

            $data['actionName']   = $this->input->post('create');
            $data['updateMethod'] = ($this->input->post('update') > '' ? $this->input->post('update') : 'update');
            $this->smartyview->smarty->assign($data);

            $crud  = "\n" . $this->smartyview->smarty->fetch($this->config->item('create_method_tpl'));
        }

        // create view
        if ($this->input->post('create_view_check')) {
            $this->smartyview->smarty->assign($data);
            $createView     = $this->smartyview->smarty->fetch($this->config->item('view_create_tpl'));
            $createViewName = $data['entity']->singular . '_' . $this->input->post('create');
            
            file_put_contents($data['project']->viewsTemplatesPath() . $createViewName . '.tpl', $createView);
            $data['entity']->compileView($createViewName);
        }

        // read controller
        if ($this->input->post('read_check')) {
            
            $data['actionName'] = $this->input->post('read');            
            $this->smartyview->smarty->assign($data);

            $crud .= "\n" .$this->smartyview->smarty->fetch($this->config->item('read_method_tpl'));
        }

        // read view
        if ($this->input->post('read_view_check')) {            
            $this->smartyview->smarty->assign($data);
            $readView     = $this->smartyview->smarty->fetch($this->config->item('view_read_tpl'));
            $readViewName = $data['entity']->singular . '_' . $this->input->post('read');

            file_put_contents($data['project']->viewsTemplatesPath() . $readViewName . '.tpl', $readView);
            $data['entity']->compileView($readViewName);
        }

        // update controller
        if ($this->input->post('update_check')) {
            
            $data['actionName'] = $this->input->post('update');
            $this->smartyview->smarty->assign($data);

            $crud .= "\n" . $this->smartyview->smarty->fetch($this->config->item('update_method_tpl'));
        }

        // update view
        if ($this->input->post('update_view_check')) {
            
            $data['deleteMethod'] = ($this->input->post('delete') > '' ? $this->input->post('delete') : 'delete');
            $this->smartyview->smarty->assign($data);
            $updateView     = $this->smartyview->smarty->fetch($this->config->item('view_update_tpl'));
            $updateViewName = $data['entity']->singular . '_' . $this->input->post('update');           

            file_put_contents($data['project']->viewsTemplatesPath() . $updateViewName . '.tpl', $updateView);
            $data['entity']->compileView($updateViewName);
        }

        // delete controller
        if ($this->input->post('delete_check')) {
            $data['actionName']   = $this->input->post('delete');
            $data['createMethod'] = ($this->input->post('create') > '' ? $this->input->post('create') : 'create');
            $this->smartyview->smarty->assign($data);

            $crud .= "\n" . $this->smartyview->smarty->fetch($this->config->item('delete_method_tpl'));
        }

        //////////////////////////////// WORKAROUND ///////////////////
        $controller = file_get_contents($data['entity']->customControllerFilePath());
        $insertArea = explode('{', $controller);
        $insertArea = $insertArea[1];
        $controller = str_replace($insertArea, "{$crud}\n{$insertArea}", $controller);
        file_put_contents($data['entity']->customControllerFilePath(), $controller);
        ///////////////////////////////////////////////////////////////////////

        $data['entity']->generateControllerFiles(false);
        redirect(base_url(). 'projects/dashboard/' . $data['project']->id . '/');
    }

    public function delete($entity_id) 
    {
        $entity  = new Entity($entity_id);
        $project = $entity->project;
        $user    = Projects::security($project->id, "member");

        $entity->remove();
      
        redirect(base_url()."projects/dashboard/".$project->id."/");
    }

    public function update_status() 
    {
        $id = $this->input->post('entity');
        $entity = new Entity($id);
        $entity->style = $this->input->post('style');
        $entity->class = $this->input->post('class');

        $saved = $entity->save();
        
        if ( !$saved ) {
            die($entity->error->string);
        }
    }

    public function remove_relation() 
    {
        $source_id = $this->input->post('source');
        $target_id = $this->input->post('target');
        
        $source = new Entity($source_id);
        $target = new Entity($target_id);

        $source->removeHasManyRelated($target_id);
        if ($target->isRelatedTo($source_id,'hasmany')) {
            $source->addHasOneRelated($target_id);
        }
        $source->generateModelFiles(false);
        $source->generateControllerFiles(false);

        if ($target->isRelatedTo($source_id)) {
            $target->removeHasOneRelated($source_id);
            $target->generateModelFiles(false);
            $target->generateControllerFiles(false);
        }
    }

    public function add_relation() 
    {
        $source_id = $this->input->post('source');
        $target_id = $this->input->post('target');

        $source = new Entity($source_id);
        if ($source->isRelatedTo($target_id)) {
            $source->removeHasOneRelated($target_id);
        }
        $source->addHasManyRelated($target_id);
        $source->generateModelFiles(false);
        $source->generateControllerFiles(false);

        $target = new Entity($target_id);
        if ( ! $target->isRelatedTo($source_id,'hasmany')) {
            $target->addHasOneRelated($source_id);
        }
        $target->generateModelFiles(false);
        $target->generateControllerFiles(false);
    }

    public function edit_custom_model($entityID)
    {
        // Checking permissions user
        $data['entity']    = new Entity($entityID);
        $data['user']      = Projects::security($data['entity']->project->id, "member");
        $data['project']   = new Project($data['entity']->project->id);
        $data['startLine'] = 1;
        $data['loadUrl']   = base_url() . 'entities/get_custom_model/' . $data['entity']->id . '/';
        $data['saveUrl']   = base_url() . 'entities/save_custom_model/' . $data['entity']->id . '/';

        $this->smartyview->render('online_editor.html', $data);
    }

    public function get_custom_model($entityID) 
    {
        $entity = new Entity($entityID);
        die(file_get_contents($entity->customModelFilePath()));
    }

    public function save_custom_model($entityID) 
    {
        $entity  = new Entity($entityID);
        file_put_contents($entity->customModelFilePath(), $this->input->post('content'));
        die(true);
    }
} // class Entities

/* End of file entities.php */
/* Location: ./application/controllers/entities.php */
